package org.hentai.service.impl;

import com.aizuda.zlm4j.structure.MK_MEDIA_SOURCE;
import com.aizuda.zlm4j.structure.MK_TRACK;
import com.sun.jna.Pointer;
import org.hentai.callback.LiveCallback;
import org.hentai.contants.MediaServerConstants;
import org.hentai.entity.*;
import org.hentai.service.LiveStreamService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import static org.hentai.context.MediaServerContext.ZLM_API;

@Service
public class LiveStreamServiceImpl implements LiveStreamService {
    @Override
    public Integer closeStreams(String schema, String app, String stream) {

        AtomicReference<Integer> count = new AtomicReference<>();

        ZLM_API.mk_media_source_for_each(Pointer.NULL, new LiveCallback.MKSourceFindCallBack(ctx -> {
            int status = ZLM_API.mk_media_source_close(ctx, 1);
            count.set(count.get() + status);
        }), schema, MediaServerConstants.DEFAULT_VHOST, app, stream);

        return count.get();
    }

    private MediaInfoResult getMediaInfoFromSource(MK_MEDIA_SOURCE ctx) {
        String app = ZLM_API.mk_media_source_get_app(ctx);
        String stream = ZLM_API.mk_media_source_get_stream(ctx);
        String schema = ZLM_API.mk_media_source_get_schema(ctx);
        int readerCount = ZLM_API.mk_media_source_get_reader_count(ctx);
        int totalReaderCount = ZLM_API.mk_media_source_get_total_reader_count(ctx);
        int trackSize = ZLM_API.mk_media_source_get_track_count(ctx);
        int originType = ZLM_API.mk_media_source_get_origin_type(ctx);

        Pointer originTypePointer = ZLM_API.mk_media_source_get_origin_type_str(ctx);
        long aliveSecond = ZLM_API.mk_media_source_get_alive_second(ctx);
        int bytesSpeed = ZLM_API.mk_media_source_get_bytes_speed(ctx);

        Pointer originUrlPointer = ZLM_API.mk_media_source_get_origin_url(ctx);
        long createStamp = ZLM_API.mk_media_source_get_create_stamp(ctx);
        int isRecordHls = ZLM_API.mk_media_source_is_recording(ctx, 0);
        int isRecordMp4 = ZLM_API.mk_media_source_is_recording(ctx, 1);

        MediaInfoResult mediaInfoResult = new MediaInfoResult();
        mediaInfoResult.setApp(app);
        mediaInfoResult.setStream(stream);
        mediaInfoResult.setSchema(schema);
        mediaInfoResult.setReaderCount(readerCount);
        mediaInfoResult.setTotalReaderCount(totalReaderCount);
        mediaInfoResult.setOriginType(originType);
        mediaInfoResult.setOriginUrl(originUrlPointer.getString(0));
        mediaInfoResult.setCreateStamp(createStamp);
        mediaInfoResult.setIsRecordingHLS(isRecordHls == 1);
        mediaInfoResult.setIsRecordingMP4(isRecordMp4 == 1);
        mediaInfoResult.setOriginTypeStr(originTypePointer.getString(0));
        mediaInfoResult.setAliveSecond(aliveSecond);
        mediaInfoResult.setBytesSpeed(bytesSpeed);

        List<Track> tracks = new ArrayList<>();

        for (int i = 0; i < trackSize; i++) {
            MK_TRACK mkTrack = ZLM_API.mk_media_source_get_track(ctx, i);
            Track track = new Track();

            int codec_id = ZLM_API.mk_track_codec_id(mkTrack);
            String codec_name = ZLM_API.mk_track_codec_name(mkTrack);
            int bit_rate = ZLM_API.mk_track_bit_rate(mkTrack);
            int is_video = ZLM_API.mk_track_is_video(mkTrack);
            int is_ready = ZLM_API.mk_track_ready(mkTrack);
            long duration = ZLM_API.mk_track_duration(mkTrack);
            long frames = ZLM_API.mk_track_frames(mkTrack);
            float loss = ZLM_API.mk_media_source_get_track_loss(ctx, mkTrack);
            track.setCodec_id(codec_id);
            track.setCodec_id_name(codec_name);
            track.setBit_rate(bit_rate);
            track.setIs_video(is_video);
            track.setDuration(duration);
            track.setReady(is_ready == 1);
            track.setFrames(frames);
            track.setLoss(loss);

            if (is_video == 1) {
                int width = ZLM_API.mk_track_video_width(mkTrack);
                track.setWidth(width);
                int height = ZLM_API.mk_track_video_height(mkTrack);
                track.setHeight(height);
                int fps = ZLM_API.mk_track_video_fps(mkTrack);
                track.setFps(fps);
                int gop_size = ZLM_API.mk_track_video_gop_size(mkTrack);
                track.setGop_size(gop_size);
                int gop_interval_ms = ZLM_API.mk_track_video_gop_interval_ms(mkTrack);
                track.setGop_interval_ms(gop_interval_ms);
                long key_frames = ZLM_API.mk_track_video_key_frames(mkTrack);
                track.setKey_frames(key_frames);
            } else {
                int sample_rate = ZLM_API.mk_track_audio_sample_rate(mkTrack);
                int audio_channel = ZLM_API.mk_track_audio_channel(mkTrack);
                int audio_sample_bit = ZLM_API.mk_track_audio_sample_bit(mkTrack);
                track.setSample_rate(sample_rate);
                track.setAudio_channel(audio_channel);
                track.setAudio_sample_bit(audio_sample_bit);
            }
            tracks.add(track);
            ZLM_API.mk_track_unref(mkTrack);

        }

        ZLM_API.mk_free(originTypePointer);
        ZLM_API.mk_free(originUrlPointer);
        mediaInfoResult.setTracks(tracks);

        return mediaInfoResult;

    }

    @Override
    public List<MediaInfoResult> getMediaList(String schema, String app, String stream) {
        List<MediaInfoResult> mediaList = new ArrayList<>();
        ZLM_API.mk_media_source_for_each(Pointer.NULL, new LiveCallback.MKSourceFindCallBack(ctx -> {
            MediaInfoResult mediaInfoResult = getMediaInfoFromSource(ctx);
            mediaList.add(mediaInfoResult);
        }), schema, MediaServerConstants.DEFAULT_VHOST, app, stream);

        return mediaList;
    }

    @Override
    public MediaInfoResult getMediaInfo(String schema, String app, String stream) {
        MK_MEDIA_SOURCE mkMediaSource = ZLM_API.mk_media_source_find2(schema, MediaServerConstants.DEFAULT_VHOST, app, stream, 0);
        if (mkMediaSource != null) {
            return getMediaInfoFromSource(mkMediaSource);
        }
        return null;

    }
}
